//===============================================================================
// Microsoft patterns & practices
// Web Client Software Factory
//-------------------------------------------------------------------------------
// Copyright (C) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//-------------------------------------------------------------------------------
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================
using System;
using System.Text;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using WCSFContrib.PageFlow.Xml.Storage.EnterpriseLibrary.Tests.Mocks;
using WCSFContrib.PageFlow.Xml.Storage.EnterpriseLibrary;
using Microsoft.Practices.EnterpriseLibrary.Data;
using System.Data;

namespace WCSFContrib.PageFlow.Xml.Storage.EnterpriseLibrary.Tests
{
    [TestClass]
    public class PageFlowInstanceCorrelationSqlProviderFixture
    {
        [ClassInitialize]
        public static void SetupDatabase(TestContext testContext)
        {
            SetupDatabaseUtility.Setup();
        }

        private const string DataBaseName = "PageFlowInstanceStateStoreProvider";

        [TestCleanup]
        public void Cleanup()
        {
            Database db = DatabaseFactory.CreateDatabase(DataBaseName);
            db.ExecuteReader(CommandType.Text, "TRUNCATE TABLE pageFlow_InstanceStateStore");
        }

        [ExpectedException(typeof(ArgumentNullException))]
        [TestMethod]
        public void CreateWithNullDatabaseFails()
        {
            string databaseName = null;
            XmlPageFlowInstanceSqlStore store = new XmlPageFlowInstanceSqlStore(databaseName);

            Assert.IsNull(store);
        }

        [ExpectedException(typeof(ArgumentException))]
        [TestMethod]
        public void CreateWithEmptyDatabaseFails()
        {
            XmlPageFlowInstanceSqlStore store = new XmlPageFlowInstanceSqlStore(String.Empty);

            Assert.IsNull(store);
        }

        [TestMethod]
        public void CanCreateWithParameters()
        {
            XmlPageFlowInstanceSqlStore store = new XmlPageFlowInstanceSqlStore(DataBaseName);
            Assert.IsNotNull(store);
        }

        [TestMethod]
        public void CanStoreInstance()
        {
            XmlPageFlowInstanceSqlStore store = new XmlPageFlowInstanceSqlStore(DataBaseName);
            XmlPageFlowInstance pageFlow = CreatePageFlowInstance(store);
            pageFlow.UserData["foo"] = new MockObject("bar");
            store.Add(pageFlow);

            Database db = DatabaseFactory.CreateDatabase(DataBaseName);
            using (
                IDataReader reader =
                    db.ExecuteReader(CommandType.Text,
                                     string.Format("SELECT * FROM pageFlow_InstanceStateStore WHERE InstanceID = '{0}'", pageFlow.InstanceId)))
            {
                reader.Read();
                Assert.AreEqual(pageFlow.InstanceId, reader.GetGuid(0));

                byte[] arrayInstance = (byte[])reader.GetValue(1);
                XmlPageFlowInstance deserializedInstance = Util.SerializationHelper.DeserializeBinaryArray<XmlPageFlowInstance>(arrayInstance);

                Assert.AreEqual(pageFlow.InstanceId, deserializedInstance.InstanceId);
                Assert.AreEqual(pageFlow.CurrentView, deserializedInstance.CurrentView);
                Assert.AreEqual(pageFlow.PageFlowType, deserializedInstance.PageFlowType);
                Assert.AreEqual(pageFlow.Status, deserializedInstance.Status);
                Assert.AreEqual(pageFlow.UserData.Keys.Count, deserializedInstance.UserData.Keys.Count);
                Assert.AreEqual(pageFlow.UserData["foo"], deserializedInstance.UserData["foo"]);
            }
        }

        [TestMethod]
        public void CanRetrieveInstance()
        {
            XmlPageFlowInstanceSqlStore store = new XmlPageFlowInstanceSqlStore(DataBaseName);
            XmlPageFlowInstance pageFlow = CreatePageFlowInstance(store);
            pageFlow.UserData["foo"] = new MockObject("bar");
            store.Add(pageFlow);

            XmlPageFlowInstance retrievedInstance = store.Get(pageFlow.InstanceId);

            Assert.AreEqual(pageFlow.InstanceId, retrievedInstance.InstanceId);
            Assert.AreEqual(pageFlow.CurrentView, retrievedInstance.CurrentView);
            Assert.AreEqual(pageFlow.PageFlowType, retrievedInstance.PageFlowType);
            Assert.AreEqual(pageFlow.Status, retrievedInstance.Status);
            Assert.AreEqual(pageFlow.UserData.Keys.Count, retrievedInstance.UserData.Keys.Count);
            Assert.AreEqual(pageFlow.UserData["foo"], retrievedInstance.UserData["foo"]);
        }

        [TestMethod]
        public void CanRemoveInstance()
        {
            XmlPageFlowInstanceSqlStore store = new XmlPageFlowInstanceSqlStore(DataBaseName);
            XmlPageFlowInstance pageFlow = CreatePageFlowInstance(store);
            store.Add(pageFlow);

            XmlPageFlowInstance retrievedInstance = store.Get(pageFlow.InstanceId);
            Assert.IsNotNull(retrievedInstance);

            store.Remove(pageFlow.InstanceId);
            retrievedInstance = store.Get(pageFlow.InstanceId);
            Assert.IsNull(retrievedInstance);
        }


        private static XmlPageFlowInstance CreatePageFlowInstance(IXmlPageFlowInstanceStore xmlPageFlowInstanceStore)
        {
            return new XmlPageFlowInstance(Guid.NewGuid(), typeof(MockPageFlowType), new MockXmlPageFlowRuntime(xmlPageFlowInstanceStore));
        }
    }

    [Serializable]
    public class MockObject
    {
        private string Foo;
        public MockObject() { }

        public MockObject(string foo)
        {
            Foo = foo;
        }

        public override bool Equals(object obj)
        {
            return Foo == ((MockObject)obj).Foo;
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
    }



}
